/**
 * User: Paulo Fournier
 * Date: 12-08-2013
 * Mobile app controller
 */

Ext.define('Mobile-app.controller.Mobile', {
    extend: 'Ext.app.Controller',

    config: {
        //add view references for this controller
        refs: {
            mainView: 'mainview',
            mobilePanel: 'mobilepanel',
            mobileDetailPanel: 'mobiledetailpanel',
            whatsAroundPanel: 'whatsaroundpanel'
        },

        //Definition of all listen events of this controller
        //can be triggered by the [fireEvent] method
        control: {

            mainView: {
                loadStore: 'onLoadStore'
            },

            mobilePanel: {
                showDetails: 'onShowDetails'
            },

            mobileDetailPanel: {
                showMarker: 'onShowMarker',
                loadEvents: 'onLoadEvents',
                whatsAround: 'onWhatsAround'
            },

            whatsAroundPanel: {
                updateWhatsAroundMarkers: 'onUpdateWhatsAroundMarkers',
                centerWhatsAroundMobile: 'onCenterWhatsAroundMobile',
                showWhatsAroundDetails: 'onShowWhatsAroundDetails'
            }

        }

    },

    /***
     * Used to show the details of a mobile
     * @param list Ext.DataView.List
     * @param record The record associated to the item
     */
    onShowDetails: function (list, record) {

        //save record information
        this.selectdRecord = record;

        var view = null;

        if (!this.getMobileDetailPanel()) {
            //create view
            view = Ext.create('Mobile-app.view.MobileDetail');

            //add view to body viewport
            Ext.Viewport.add(view);
        }
        else {
            view = this.getMobileDetailPanel();
            view.show();
        }

        //show loading mask
        view.setMasked({
            xtype: 'loadmask',
            message: $.t('main.loading').toLowerCase() + '...'
        });

        //get vehicle details
        Ext.Ajax.request({

            url: 'app/php/public/mobile.detail.php',
            method: 'post',
            record: record,
            scope: this,
            params: {
                id: record.get('id')
            },

            /***
             * Callback method
             * Called when the AJAX request is performed successfully
             * @param response The response object
             */
            success: function (response, options) {

                var view = this.getMobileDetailPanel(),
                    listPanel = view.down('list');

                //hide the loading mask
                view.setMasked(false);

                try {

                    //get the JSON object response
                    var rst = Ext.JSON.decode(response.responseText);

                    //check if the authentication was performed successfully
                    if (rst.id) {

                        //merge external data with record
                        for (key in rst) {
                            options.record.set(key, rst[key]);
                        }

                        //set record to all view panels
                        view.items.first().items.each(function (p) {
                            p.setRecord(options.record)
                        });

                        view.fireEvent('loadEvents', listPanel);

                        //get map object
                        var map = view.down('map').getMap();

                        //if map no found, do nothing!
                        if (map) {

                            //set position
                            var latLong = new google.maps.LatLng(options.record.get('latitude'), options.record.get('longitude'));

                            //only update map if the record was found
                            if (!map.marker)
                                map.marker = new google.maps.Marker({
                                    position: latLong,
                                    map: map
                                });
                            else
                                map.marker.setPosition(latLong);

                            //center map
                            map.setCenter(latLong);

                        }
                    }
                    else {
                        //otherwise, show the failure auth message
                        console.log('error !success');
                    }

                } catch (e) {
                    console.log(e.toString());
                }

            },

            /***
             * Callback method
             * Called when the AJAX request is performed unsuccessfully
             * @param response The response object
             */
            failure: function (response) {
                this.getMobileDetailPanel().hide();
                console.log($.t('error.6', {error: response.statusText}));
            }

        });

    },

    /***
     * Will show the vehicle marker on the map and center it
     * @param mapPanel The map object Ext.Map
     */
    onShowMarker: function (mapPanel) {

        //set position
        var record = this.selectdRecord,
            map = mapPanel.getMap(),
            latLong = new google.maps.LatLng(record.get('latitude'), record.get('longitude'));

        //check if marker exists, if so, only update the position
        if (!map.marker)
            map.marker = new google.maps.Marker({
                position: latLong,
                map: map
            });
        else
            map.marker.setPosition(latLong);

        //center map
        map.setCenter(latLong);

    },

    /***
     * Will load the list store with events
     * @param listPanel
     */
    onLoadEvents: function (listPanel) {

        if (!listPanel) return;

        var eventRecords = this.selectdRecord.get('relatedEvents'),
            store = listPanel.getStore();

        store.removeAll();

        //set records
        store.setData(eventRecords);

    },

    /***
     * Will find the closest vehicles
     */
    onWhatsAround: function () {

        var list = null;

        //hide mobile detail panel
        this.getMobileDetailPanel().hide();

        if (!this.getWhatsAroundPanel()) {
            //add view to body viewport
            Ext.Viewport.add(Ext.create('Mobile-app.view.WhatsAround'));

            list = this.getWhatsAroundPanel().down('list');

            list.getStore().on({
                beforeload: this.beforeWhatsAroundListLoad,
                load: this.afterWhatsAroundListLoad,
                scope: this
            });
        }
        else
            list = this.getWhatsAroundPanel().down('list');

        //reload store to get the mobile vs distance list
        list.getStore().load({
            params: {id: this.selectdRecord.get('id')}
        });

    },

    /***
     * Fires before a request is made for a new data object.
     * If the beforeload handler returns false the load action will be canceled. Note that you should not listen for this event in order to refresh the data view
     * @param store This Store
     * @param operation The Ext.data.Operation object that will be passed to the Proxy to load the Store
     * @param eOpts The options object passed to Ext.util.Observable.addListener
     */
    beforeWhatsAroundListLoad: function (store, operation, eOpts) {

        //show loading mask
        this.getMobilePanel().setMasked({
            xtype: 'loadmask',
            message: $.t('main.loading').toLowerCase() + '...'
        });

    },

    /***
     * Fires whenever records have been loaded into the store
     * @param store This Store
     * @param records An array of records
     * @param successful True if the operation was successful
     * @param operation The associated operation
     * @param eOpts The options object passed to Ext.util.Observable.addListener
     */
    afterWhatsAroundListLoad: function (store, records, successful, operation, eOpts) {

        this.getMobilePanel().setMasked(false);
        this.getWhatsAroundPanel().show();

        var map = this.getWhatsAroundPanel().down('map').getMap();

        if (map) {
            for (i in map.markers)
                map.markers[i].setMap(null);

            if (map.polyline)
                map.polyline.setMap(null);

            this.onUpdateWhatsAroundMarkers();
        }

    },

    /***
     * Show all markers on map
     */
    onUpdateWhatsAroundMarkers: function () {

        var store = this.getWhatsAroundPanel().down('list').getStore(),
            max = store.getCount() >= 10 ? 10 : store.getCount(),
            bounds = new google.maps.LatLngBounds(),
            center = new google.maps.LatLng(this.selectdRecord.get('latitude'), this.selectdRecord.get('longitude')),
            map = this.getWhatsAroundPanel().down('map').getMap();

        //reload markers object
        map.markers = [];

        //add marker
        map.markers.push(new google.maps.Marker({
            position: center,
            title: this.selectdRecord.get('reference'),
            map: map,
            icon: new google.maps.MarkerImage(
                'resources/icons/level/none.png',
                new google.maps.Size(16, 16)
            )
        }));

        //set markers
        for (var i = 0; i < max; i++) {

            var record = store.getAt(i),
                pos = new google.maps.LatLng(record.get('latitude'), record.get('longitude'));

            map.markers.push(new google.maps.Marker({
                position: pos,
                title: record.get('reference'),
                map: map,
                icon: new google.maps.MarkerImage(
                    'resources/icons/level/' + ((i <= 3) ? 'green' : (i > 5 ? 'red' : 'orange')) + '.png',
                    new google.maps.Size(16, 16)
                )
            }));

            bounds.extend(pos);
        }

        map.fitBounds(bounds);
    },

    /***
     * Called whenever an item of this list is tapped
     * @param list Ext.DataView.List
     * @param record The record associated to the item
     */
    onCenterWhatsAroundMobile: function (list, record) {

        var map = this.getWhatsAroundPanel().down('map').getMap(),
            pos = new google.maps.LatLng(record.get('latitude'), record.get('longitude'));

        map.setCenter(pos);

    },

    /***
     * Fires whenever a disclosure is handled
     * @param list Ext.DataView.List
     * @param record The record associated to the item
     * @param index The index of the item tapped
     */
    onShowWhatsAroundDetails: function (list, record, index) {

        //select record on list and suppress event
        list.select(record, false, true);

        var map = this.getWhatsAroundPanel().down('map').getMap(),
            bounds = new google.maps.LatLngBounds(),
            end = new google.maps.LatLng(this.selectdRecord.get('latitude'), this.selectdRecord.get('longitude')),
            ini = new google.maps.LatLng(record.get('latitude'), record.get('longitude'));

        //set bounds
        bounds.extend(ini); //"from" vehicle
        bounds.extend(end); //"to" vehicle
        bounds.extend(new google.maps.LatLng(record.get('bounds').northeast.lat, record.get('bounds').northeast.lng)); //max northeast
        bounds.extend(new google.maps.LatLng(record.get('bounds').southwest.lat, record.get('bounds').southwest.lng)); //max southwest
        //fit bounds
        map.fitBounds(bounds);

        //decode polyline path
        var path = google.maps.geometry.encoding.decodePath(record.get('polyline')),
            list = [ini]; //vehicle position to the polyline

        //create polyline list
        for (var i = 0; i < path.length; ++i) {
            list.push(new google.maps.LatLng(path[i].lat(), path[i].lng()));
        }

        //vehicle position to the polyline
        list.push(end);

        //remove any existing polyline
        if (map.polyline)
            map.polyline.setMap(null);

        //add polyline to map
        map.polyline = new google.maps.Polyline({
            path: list,
            strokeColor: "#FF0000",
            strokeOpacity: 0.8,
            strokeWeight: 7,
            clickable: false,
            map: map
        });

    },

    /***
     * It's called after a successfully
     */
    onLoadStore: function(){

        var view = this.getMobilePanel(),
            listPanel = view.down('list');

        //reload store
        listPanel.getStore().load();
    }

});